package ar.com.fiuba.ElectronicCircuitAnalyst.application.impl;

import java.util.List;

import org.apache.log4j.Logger;

import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.CircuitService;
import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.dto.CircuitDto;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.Circuit;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.CircuitFactory;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.CircuitRepository;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.AlreadyExistingCircuitElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.CircuitElementNotFoundException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.DuplicateElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.InvalidCircuitElementException;

public class CircuitServiceImpl implements CircuitService {

	private Logger log = Logger.getLogger(CircuitServiceImpl.class);

	private CircuitFactory circuitFactory;

	private CircuitRepository circuitRepository;

	public CircuitServiceImpl(CircuitFactory circuitFactory, CircuitRepository circuitRepository) {
		this.circuitFactory = circuitFactory;
		this.circuitRepository = circuitRepository;
	}

	public void makeCircuit(CircuitDto data) throws InvalidCircuitElementException,
			AlreadyExistingCircuitElementException {
		log.info("Making \"" + data.getName() + "\" circuit.");
		try {
			circuitRepository.save(circuitFactory.makeCircuit(data));
		} catch (DuplicateElementException e) {
			throw new AlreadyExistingCircuitElementException("Circuit with name \"" + data.getName()
					+ "\" already exists.");
		}
	}

	public void modifyCircuit(CircuitDto data) throws InvalidCircuitElementException, CircuitElementNotFoundException {
		log.info("Modifying \"" + data.getName() + "\" circuit.");
		removeCircuit(data.getName());
		try {
			makeCircuit(data);
		} catch (AlreadyExistingCircuitElementException e) {
			// Should never reach this since circuit has just been removed,
			// but just in case...
			throw new RuntimeException("Unreachable code reached...");
		}
	}

	public void removeCircuit(String name) throws CircuitElementNotFoundException, InvalidCircuitElementException {
		log.info("Removing \"" + name + "\" circuit.");
		circuitRepository.removeCircuitByName(name);
	}

	public void removeRelatedCircuits(String name) throws InvalidCircuitElementException {
		List<Circuit> relatedCircuits = circuitRepository.getRelatedCircuits(name);
		for (Circuit circuit : relatedCircuits) {
			try {
				removeCircuit(circuit.getName());
			} catch (CircuitElementNotFoundException e) {
				// Should never reach this since circuit has just been
				// retrieved, but just in case...
				throw new RuntimeException("Unreachable code reached...");
			}
		}
	}
}
